import Foundation
import Vapor
import NIOCore
import AsyncHTTPClient
import Crypto

struct TencentEmailService {
    private let secretId: String
    private let secretKey: String
    private let endpoint: String
    private let regionId: String
    private let fromEmailAddress: String
    private let domain: String
    
    // 添加模板ID配置
    private let registerTemplateId: Int     // 注册验证模板
    private let loginTemplateId: Int        // 登录验证模板
    private let resetPasswordTemplateId: Int // 重置密码模板
    private let bindEmailTemplateId: Int    // 邮箱绑定模板
    
    init(
        secretId: String, 
        secretKey: String, 
        endpoint: String, 
        regionId: String, 
        fromEmailAddress: String, 
        domain: String,
        registerTemplateId: Int = 0,        // 注册验证模板ID
        loginTemplateId: Int = 0,           // 登录验证模板ID
        resetPasswordTemplateId: Int = 0,   // 重置密码模板ID
        bindEmailTemplateId: Int = 0        // 邮箱绑定模板ID
    ) {
        self.secretId = secretId
        self.secretKey = secretKey
        self.endpoint = endpoint
        self.regionId = regionId
        self.fromEmailAddress = fromEmailAddress
        self.domain = domain
        self.registerTemplateId = registerTemplateId
        self.loginTemplateId = loginTemplateId
        self.resetPasswordTemplateId = resetPasswordTemplateId
        self.bindEmailTemplateId = bindEmailTemplateId
        
        print("[TencentEmail] 服务初始化完成: endpoint=\(endpoint), fromEmailAddress=\(fromEmailAddress)")
    }
    
    // 发送注册验证码邮件
    func sendRegisterEmail(to email: String, code: String) async throws {
        print("[TencentEmail] 开始发送注册验证邮件到: \(email), 验证码: \(code)")
        
        if registerTemplateId > 0 {
            // 构建模板数据
            let templateData = ["验证码": code]
            let jsonData = try JSONSerialization.data(withJSONObject: templateData)
            let templateDataStr = String(data: jsonData, encoding: .utf8) ?? "{}"
            
            try await sendTemplateEmail(
                to: email,
                subject: "【巴砚教育】注册验证码",
                templateId: registerTemplateId,
                templateData: templateDataStr
            )
        } else {
            throw Abort(.internalServerError, reason: "未配置注册验证码邮件模板ID")
        }
    }
    
    // 发送登录验证码邮件
    func sendLoginEmail(to email: String, code: String) async throws {
        print("[TencentEmail] 开始发送登录验证邮件到: \(email), 验证码: \(code)")
        
        if loginTemplateId > 0 {
            // 构建模板数据
            let templateData = ["验证码": code]
            let jsonData = try JSONSerialization.data(withJSONObject: templateData)
            let templateDataStr = String(data: jsonData, encoding: .utf8) ?? "{}"
            
            try await sendTemplateEmail(
                to: email,
                subject: "【巴砚教育】登录验证码",
                templateId: loginTemplateId,
                templateData: templateDataStr
            )
        } else {
            throw Abort(.internalServerError, reason: "未配置登录验证码邮件模板ID")
        }
    }
    
    // 发送重置密码邮件
    func sendResetPasswordEmail(to email: String, code: String) async throws {
        print("[TencentEmail] 开始发送重置密码邮件到: \(email), 验证码: \(code)")
        
        if resetPasswordTemplateId > 0 {
            let templateData = ["验证码": code]
            let jsonData = try JSONSerialization.data(withJSONObject: templateData)
            let templateDataStr = String(data: jsonData, encoding: .utf8) ?? "{}"
            
            try await sendTemplateEmail(
                to: email,
                subject: "【巴砚教育】重置密码验证码",
                templateId: resetPasswordTemplateId,
                templateData: templateDataStr
            )
        } else {
            throw Abort(.internalServerError, reason: "未配置重置密码邮件模板ID")
        }
    }
    
    // 发送邮箱绑定验证码邮件
    func sendBindEmailVerificationEmail(to email: String, code: String) async throws {
        print("[TencentEmail] 开始发送邮箱绑定验证码邮件到: \(email), 验证码: \(code)")
        
        if bindEmailTemplateId > 0 {
            let templateData = ["验证码": code]
            let jsonData = try JSONSerialization.data(withJSONObject: templateData)
            let templateDataStr = String(data: jsonData, encoding: .utf8) ?? "{}"
            
            try await sendTemplateEmail(
                to: email,
                subject: "【巴砚教育】邮箱绑定验证",
                templateId: bindEmailTemplateId,
                templateData: templateDataStr
            )
        } else {
            throw Abort(.internalServerError, reason: "未配置邮箱绑定验证码邮件模板ID")
        }
    }
    
    // 使用模板发送邮件
    private func sendTemplateEmail(to email: String, subject: String, templateId: Int, templateData: String) async throws {
        print("[TencentEmail] 准备使用模板ID(\(templateId))发送邮件...")
        
        // 准备请求参数
        let timestamp = Int(Date().timeIntervalSince1970)
        
        // 构建请求体
        let requestBody: [String: Any] = [
            "FromEmailAddress": fromEmailAddress,
            "Destination": [email],
            "Subject": subject,
            "Template": [
                "TemplateID": templateId,
                "TemplateData": templateData
            ]
        ]
        
        // 打印请求体用于调试
        print("[TencentEmail] 请求体: \(requestBody)")
        
        // 准备HTTP请求
        let jsonData = try JSONSerialization.data(withJSONObject: requestBody)
        let jsonString = String(data: jsonData, encoding: .utf8) ?? ""
        
        var request = HTTPClientRequest(url: "https://\(endpoint)")
        request.method = .POST
        request.headers.add(name: "Content-Type", value: "application/json")
        request.headers.add(name: "Host", value: endpoint)
        request.headers.add(name: "X-TC-Action", value: "SendEmail")
        request.headers.add(name: "X-TC-Version", value: "2020-10-02")
        request.headers.add(name: "X-TC-Region", value: regionId)
        request.headers.add(name: "X-TC-Timestamp", value: "\(timestamp)")
        
        // 生成签名
        let authorization = try generateTC3HMACAuthorization(
            httpMethod: "POST",
            canonicalUri: "/",
            canonicalQueryString: "",
            canonicalHeaders: "content-type:application/json\nhost:\(endpoint)\n",
            signedHeaders: "content-type;host",
            payload: jsonString,
            timestamp: timestamp,
            service: "ses"
        )
        
        request.headers.add(name: "Authorization", value: authorization)
        request.body = .bytes(ByteBuffer(data: jsonData))
        
        do {
            // 发送请求 - 修复弃用警告
            let client = HTTPClient(eventLoopGroupProvider: .singleton)
            // 修复异步上下文中的syncShutdown警告
            defer { 
                Task { 
                    try await client.shutdown() 
                }
            }
            
            let response = try await client.execute(request, deadline: .now() + .seconds(30))
            
            // 处理响应
            if response.status.code >= 200 && response.status.code < 300 {
                // 读取响应内容
                let responseBody = try await response.body.collect(upTo: 1024 * 1024) // 最大1MB
                let responseData = Data(responseBody.readableBytesView)
                
                if !responseData.isEmpty {
                    let jsonResponse = try JSONSerialization.jsonObject(with: responseData) as? [String: Any]
                    print("[TencentEmail] 发送成功, Response: \(jsonResponse ?? [:])")
                } else {
                    print("[TencentEmail] 发送成功，但响应体为空")
                }
            } else {
                // 读取错误内容
                let responseBody = try await response.body.collect(upTo: 1024 * 1024) // 最大1MB
                let responseData = Data(responseBody.readableBytesView)
                
                if !responseData.isEmpty {
                    let errorMessage = String(data: responseData, encoding: .utf8) ?? "未知错误"
                    print("[TencentEmail] 发送失败: \(response.status), 错误信息: \(errorMessage)")
                    throw Abort(.internalServerError, reason: "邮件发送失败: \(errorMessage)")
                } else {
                    throw Abort(.internalServerError, reason: "邮件发送失败: HTTP状态码 \(response.status.code)")
                }
            }
        } catch {
            print("[TencentEmail] 发送请求异常: \(error)")
            throw Abort(.internalServerError, reason: "邮件发送失败: \(error.localizedDescription)")
        }
    }
    
    // 生成腾讯云API TC3-HMAC-SHA256签名
    private func generateTC3HMACAuthorization(
        httpMethod: String,
        canonicalUri: String,
        canonicalQueryString: String,
        canonicalHeaders: String,
        signedHeaders: String,
        payload: String,
        timestamp: Int,
        service: String
    ) throws -> String {
        // 参考腾讯云签名文档: https://cloud.tencent.com/document/product/1288/51057
        
        // 1. 生成规范请求串
        let hashedPayload = SHA256.hash(data: payload.data(using: .utf8)!).hex
        let canonicalRequest = [
            httpMethod,
            canonicalUri,
            canonicalQueryString,
            canonicalHeaders,
            signedHeaders,
            hashedPayload
        ].joined(separator: "\n")
        
        // 2. 生成待签名字符串
        let date = formattedDate(timestamp: timestamp)
        // 重要：根据官方示例，credentialScope不应包含region
        let credentialScope = "\(date)/\(service)/tc3_request"
        let hashedCanonicalRequest = SHA256.hash(data: canonicalRequest.data(using: .utf8)!).hex
        let stringToSign = [
            "TC3-HMAC-SHA256",
            String(timestamp),
            credentialScope,
            hashedCanonicalRequest
        ].joined(separator: "\n")
        
        // 3. 计算签名
        // 使用与官方示例相同的签名计算过程
        let keyData = "TC3\(secretKey)".data(using: .utf8)!
        let dateData = date.data(using: .utf8)!
        let secretDate = HMAC<SHA256>.authenticationCode(for: dateData, using: SymmetricKey(data: keyData))
        
        let serviceData = service.data(using: .utf8)!
        let secretService = HMAC<SHA256>.authenticationCode(for: serviceData, using: SymmetricKey(data: secretDate))
        
        let signingData = "tc3_request".data(using: .utf8)!
        let secretSigning = HMAC<SHA256>.authenticationCode(for: signingData, using: SymmetricKey(data: secretService))
        
        let stringToSignData = stringToSign.data(using: .utf8)!
        let signature = HMAC<SHA256>.authenticationCode(for: stringToSignData, using: SymmetricKey(data: secretSigning)).hex
        
        // 4. 组合Authorization
        return "TC3-HMAC-SHA256 Credential=\(secretId)/\(credentialScope), SignedHeaders=\(signedHeaders), Signature=\(signature)"
    }
    
    // 格式化日期为YYYYMMDD
    private func formattedDate(timestamp: Int) -> String {
        let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"  // 修改为带连字符的格式，符合腾讯云要求
        formatter.timeZone = TimeZone(identifier: "UTC")
        return formatter.string(from: date)
    }
}

// MARK: - 字节数组扩展
extension Sequence where Element == UInt8 {
    var hex: String {
        return self.map { String(format: "%02x", $0) }.joined()
    }
} 
